import logging
import time
import json

import numpy as np
from PyQt5.QtCore import QThread, pyqtSignal
from instrument_controller import InstrumentController
from frequencies import all_frequencies


class CalibrationThread(QThread):
    """用于执行校准任务的线程类"""
    # 定义信号，用于向主线程传递信息
    progress_signal = pyqtSignal(int)  # 进度百分比
    log_signal = pyqtSignal(str)       # 日志信息
    finished_signal = pyqtSignal(bool) # 校准完成信号，参数表示是否成功
    
    def __init__(self, attenuator, sg_widget, sa_widget, start_freq, stop_freq, step_freq, 
                 start_att, stop_att, step_att, rbw_1, vbw_1, span_1, rbw_2, vbw_2, span_2, 
                 reference_loss_data=None, specify_frequency_enabled=False):
        super().__init__()
        self.attenuator = attenuator
        self.sg_widget = sg_widget
        self.sa_widget = sa_widget
        
        # 频率参数
        self.start_freq = start_freq
        self.stop_freq = stop_freq
        self.step_freq = step_freq
        
        # 衰减器参数
        self.start_att = start_att
        self.stop_att = stop_att
        self.step_att = step_att
        
        # 仪器参数
        self.rbw_1 = rbw_1
        self.vbw_1 = vbw_1
        self.span_1 = span_1
        self.rbw_2 = rbw_2
        self.vbw_2 = vbw_2
        self.span_2 = span_2
        
        # 参考线线损数据
        self.reference_loss_data = reference_loss_data or {}
        
        # 指定频率选项
        self.specify_frequency_enabled = specify_frequency_enabled
        
        # 用于控制线程暂停/停止
        self._is_paused = False
        self._is_running = True
        
        # 用于存储校准结果
        self.calibration_data = {}

        self.current_freq = 0
        
        # 初始化仪表操作控制器
        self.instrument_controller = InstrumentController(self)
        # 连接日志信号
        self.instrument_controller.log_signal.connect(self.log_signal.emit)

    def _generate_frequency_list(self):
        """
        生成频率列表，包含常规范围频率和指定特殊频率（如果启用）
        返回去重并排序的频率列表
        """
        # 生成常规频率范围
        regular_frequencies = self._range(self.start_freq, self.stop_freq, self.step_freq)
        
        # 如果启用了指定频率选项，添加特殊频率点
        if self.specify_frequency_enabled:
            # 筛选在测试范围内的特殊频率点
            filtered_special_frequencies = [
                freq for freq in all_frequencies 
                if self.start_freq <= freq <= self.stop_freq
            ]
            
            # 合并常规频率和特殊频率
            combined_frequencies = regular_frequencies + filtered_special_frequencies
            
            # 去重并排序
            unique_frequencies = sorted(list(set(combined_frequencies)))
            
            self.log_signal.emit(
                f"频率设置: 常规频率{len(regular_frequencies)}个, "
                f"特殊频率{len(filtered_special_frequencies)}个, "
                f"合并去重后{len(unique_frequencies)}个"
            )
            
            return unique_frequencies
        else:
            # 只使用常规频率
            self.log_signal.emit(f"频率设置: 使用常规频率范围，共{len(regular_frequencies)}个频率点")
            return regular_frequencies

    def _generate_att_list(self):
        """
        生成频率列表，包含常规范围频率和指定特殊频率（如果启用）
        返回去重并排序的频率列表
        """
        # 生成常规频率范围
        regular_atts = self._range(self.start_att, self.stop_att, self.step_att)

        filtered_special_atts = [i for i in range(65, 90, 1)]

        # 合并常规频率和特殊频率
        combined_atts = regular_atts + filtered_special_atts

        # 去重并排序
        unique_atts = sorted(list(set(combined_atts)))

        return unique_atts

        
    def run(self):
        """线程主函数"""
        try:
            self.log_signal.emit("开始校准...")
            
            # 初始化信号源和频谱仪
            if not self.instrument_controller.initialize_instruments(
                self.sg_widget, self.sa_widget, self.attenuator):
                self.finished_signal.emit(False)
                return
            
            # 设置频谱仪基本配置
            self.instrument_controller.setup_sa_basic_config()
            
            # 计算总步骤数用于进度显示
            # 生成实际的频率列表
            frequency_list = self._generate_frequency_list()

            freq_steps = len(frequency_list)
            att_steps = int((self.stop_att - self.start_att) / self.step_att) + 1
            total_steps = freq_steps * att_steps
            current_step = 0

            att_list = self._generate_att_list()

            # 校准主循环
            for freq in frequency_list:
                if not self._is_running:
                    break
                for att_value in att_list:
                    if not self._is_running:
                        break

                    # 执行完整的测量流程
                    try:
                        sg_level, measured_value = self.instrument_controller.perform_complete_measurement(
                            freq, att_value, self.rbw_1, self.vbw_1, self.span_1,
                            self.rbw_2, self.vbw_2, self.span_2)
                    except Exception as e:
                        self.log_signal.emit(f"测量失败: {str(e)}")
                        continue
                    
                    # 记录数据
                    self._record_data(freq, sg_level, att_value, measured_value)
                    
                    # 更新进度
                    current_step += 1
                    progress = int((current_step / total_steps) * 100)
                    self.progress_signal.emit(progress)
                    
                    # 检查是否需要暂停
                    while self._is_paused and self._is_running:
                        time.sleep(0.1)
            
            self.log_signal.emit("校准完成")
            self.instrument_controller.shutdown_instruments()
            # 保存校准结果到JSON文件
            self._save_calibration_data()
            self.finished_signal.emit(True)
            
        except Exception as e:
            logging.error(f"校准过程中出错: {str(e)}")
            self.log_signal.emit(f"校准过程中出错: {str(e)}")
            self.finished_signal.emit(False)
    



    def _record_data(self, frequency, sg_level, attenuation, measured_value):
        """记录测量数据"""
        # 获取参考线线损
        reference_loss = self.instrument_controller.get_reference_loss(
            frequency, self.reference_loss_data)
        
        # 计算真实的衰减值
        compensated_value, actual_attenuation = self.instrument_controller.calculate_actual_attenuation(
            sg_level, measured_value, reference_loss)
        
        # 四舍五入到两位小数
        reference_loss = round(reference_loss, 2)
        measured_value = round(measured_value, 2)

        # 记录日志信息
        if reference_loss != 0:
            self.log_signal.emit(
                f"记录数据: 频率={frequency}MHz, 设定衰减={attenuation}dB, "
                f"信号源={sg_level}dBm, 原始测量={measured_value}dBm, "
                f"参考线线损={reference_loss}dB, 补偿后={compensated_value}dBm, "
                f"真实衰减={actual_attenuation}dB"
            )
        else:
            self.log_signal.emit(
                f"记录数据: 频率={frequency}MHz, 设定衰减={attenuation}dB, "
                f"信号源={sg_level}dBm, 测量值={measured_value}dBm, "
                f"真实衰减={actual_attenuation}dB (未使用参考线线损)"
            )
        
        # 将数据存储到校准结果字典中
        # 使用衰减器值作为主键
        if frequency not in self.calibration_data:
            self.calibration_data[frequency] = {}
        
        # 使用频率作为子键，直接存储真实衰减值
        self.calibration_data[frequency][attenuation] = actual_attenuation

    def _range(self, start, stop, step):
        """生成浮点数范围"""
        values = []
        current = start
        while current <= stop:
            values.append(current)
            current += step
        return values
    
    def _save_calibration_data(self):
        """保存校准数据到JSON文件"""
        try:
            # 生成文件名，包含时间戳
            timestamp = time.strftime("%Y%m%d_%H%M%S")
            filename = f"calibration_data_{timestamp}.json"
            
            # 保存数据到JSON文件
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(self.calibration_data, f, ensure_ascii=False, indent=4)
            
            self.log_signal.emit(f"校准数据已保存到 {filename}")
        except Exception as e:
            self.log_signal.emit(f"保存校准数据时出错: {str(e)}")
    
    def pause(self):
        """暂停校准"""
        self._is_paused = True
    
    def resume(self):
        """恢复校准"""
        self._is_paused = False
    
    def stop(self):
        """停止校准"""
        self._is_running = False
        self._is_paused = False